/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package splab.ufcg.edu.br.trace.gui;

import java.util.Map;
import java.util.Set;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import splab.ufcg.edu.br.trace.entities.TraceLinkList;
import splab.ufcg.edu.br.trace.enumeration.TraceLinkElementEnum;
import splab.ufcg.edu.br.trace.facade.TraceabilityFacade;
import splab.ufcg.edu.br.trace.query.entities.TraceQuery;

/**
 * 
 * @author Arthur
 */
public class QueryFrame extends javax.swing.JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8741928128061293161L;

	private TraceabilityFacade facade;

	private Map<String, TraceQuery> mapQueries;

	private boolean expand;

	private javax.swing.JPanel buttonPanel;
    private javax.swing.JButton closeButton;
    private javax.swing.JLabel closeIcon;
    private javax.swing.JButton filterButton;
    private javax.swing.JComboBox filterFieldComboBox;
    private javax.swing.JComboBox filterValueComboBox;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JLabel messageLabel;
    private javax.swing.JPanel queryFunctionalitiesPanel;
    private javax.swing.JList queryList;
    private javax.swing.JScrollPane queryPanel;
    private javax.swing.JScrollPane queryParameterPanel;
    private javax.swing.JTextArea queryParameterTextArea;
    private javax.swing.JPanel queryResultPanel;
    private javax.swing.JButton runButton;
    private javax.swing.JLabel runIcon;
    private splab.ufcg.edu.br.trace.gui.TraceTreeRepresenter traceTreeRepresenter;
	

	/**
	 * Creates new form QueryFrame
	 */
	public QueryFrame(Map<String, TraceQuery> mapQueries) {
		this.facade = TraceabilityFacade.getInstance();

		this.mapQueries = mapQueries;

		initComponents();

		expand = false;

		queryList.addListSelectionListener(new QuerySelectionListener());

		setVisible(true);
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	// <editor-fold defaultstate="collapsed"
	// <editor-fold defaultstate="collapsed"
	// <editor-fold defaultstate="collapsed"
	// <editor-fold defaultstate="collapsed"
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        this.initVariables();

        this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        this.initButtons();

        this.setButtonsLayout();

        queryFunctionalitiesPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        queryPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Available Queries"));

        queryList.setModel(new javax.swing.AbstractListModel() {
            Set<String> queriesSet = mapQueries.keySet();
            String[] queriesArray = queriesSet.toArray(new String[0]);
            public int getSize() { return queriesArray.length; }
            public Object getElementAt(int i) { return queriesArray[i]; }
        });
        queryPanel.setViewportView(queryList);

        queryParameterPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Edit Query Parameters"));

        queryParameterTextArea.setColumns(20);
        queryParameterTextArea.setRows(5);
        queryParameterPanel.setViewportView(queryParameterTextArea);

        javax.swing.GroupLayout queryFunctionalitiesPanelLayout = new javax.swing.GroupLayout(queryFunctionalitiesPanel);
        queryFunctionalitiesPanel.setLayout(queryFunctionalitiesPanelLayout);
        queryFunctionalitiesPanelLayout.setHorizontalGroup(
            queryFunctionalitiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(queryFunctionalitiesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(queryFunctionalitiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(queryPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(queryParameterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 248, Short.MAX_VALUE))
                .addContainerGap())
        );
        queryFunctionalitiesPanelLayout.setVerticalGroup(
            queryFunctionalitiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(queryFunctionalitiesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(queryPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(queryParameterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
                .addContainerGap())
        );

        queryResultPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        filterFieldComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Select" }));
        filterFieldComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                filterFieldComboBoxActionPerformed(evt);
            }
        });

        filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Select" }));

        filterButton.setText("Filter");
        filterButton.setPreferredSize(new java.awt.Dimension(76, 27));
        filterButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                filterButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout queryResultPanelLayout = new javax.swing.GroupLayout(queryResultPanel);
        queryResultPanel.setLayout(queryResultPanelLayout);
        queryResultPanelLayout.setHorizontalGroup(
            queryResultPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(queryResultPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(filterFieldComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(62, 62, 62)
                .addComponent(filterValueComboBox, 0, 232, Short.MAX_VALUE)
                .addGap(74, 74, 74)
                .addComponent(filterButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        queryResultPanelLayout.setVerticalGroup(
            queryResultPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, queryResultPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(queryResultPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(filterFieldComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(filterValueComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(filterButton, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(queryFunctionalitiesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(queryResultPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(traceTreeRepresenter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addComponent(buttonPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(traceTreeRepresenter, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(queryResultPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(queryFunctionalitiesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void setButtonsLayout() {
		javax.swing.GroupLayout buttonPanelLayout = new javax.swing.GroupLayout(buttonPanel);
        buttonPanel.setLayout(buttonPanelLayout);
        buttonPanelLayout.setHorizontalGroup(
            buttonPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(buttonPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(buttonPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(messageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(buttonPanelLayout.createSequentialGroup()
                        .addComponent(runIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(runButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(closeIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(closeButton))
                    .addComponent(jSeparator1))
                .addContainerGap())
        );
        buttonPanelLayout.setVerticalGroup(
            buttonPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(messageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(buttonPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(runButton)
                    .addComponent(runIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(closeIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(closeButton))
                .addContainerGap())
        );
	}

	private void initButtons() {
		buttonPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        closeButton.setText("Close");
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        runButton.setText("Run Query");
        runButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                runButtonActionPerformed(evt);
            }
        });

        runIcon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/run.png"))); // NOI18N
        runIcon.setPreferredSize(new java.awt.Dimension(27, 27));

        closeIcon.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/exit.png"))); // NOI18N
        closeIcon.setPreferredSize(new java.awt.Dimension(27, 27));
	}

	private void initVariables() {
		buttonPanel = new javax.swing.JPanel();
        closeButton = new javax.swing.JButton();
        runButton = new javax.swing.JButton();
        runIcon = new javax.swing.JLabel();
        closeIcon = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        messageLabel = new javax.swing.JLabel();
        queryFunctionalitiesPanel = new javax.swing.JPanel();
        queryPanel = new javax.swing.JScrollPane();
        queryList = new javax.swing.JList();
        queryParameterPanel = new javax.swing.JScrollPane();
        queryParameterTextArea = new javax.swing.JTextArea();
        queryResultPanel = new javax.swing.JPanel();
        filterFieldComboBox = new javax.swing.JComboBox();
        filterValueComboBox = new javax.swing.JComboBox();
        filterButton = new javax.swing.JButton();
        traceTreeRepresenter = new splab.ufcg.edu.br.trace.gui.TraceTreeRepresenter();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void filterFieldComboBoxActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_filterFieldComboBoxActionPerformed

		int selectedIndex = filterFieldComboBox.getSelectedIndex();

		switch (selectedIndex) {
		case 0:
			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					new String[] { "Select" }));
			break;

		case 1:

			Set<String> requirementsList = traceTreeRepresenter.getLastQueriedResult().getRequirements();

			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					requirementsList.toArray()));

			break;

		case 2:

			Set<String> semanticList = traceTreeRepresenter.getLastQueriedResult().getSemantics();

			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					semanticList.toArray()));

			break;

		case 3:

			Set<String> typesList = traceTreeRepresenter.getLastQueriedResult().getArtifactTypes();

			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					typesList.toArray()));

			break;

		case 4:

			Set<String> artifactsList = traceTreeRepresenter.getLastQueriedResult().getArtifacts();

			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					artifactsList.toArray()));

			break;

		default:
			filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					new String[] { "Select" }));
			break;
		}

	}// GEN-LAST:event_filterFieldComboBoxActionPerformed

	@SuppressWarnings("unused")
	private void expandCollapseButtonActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_expandCollapseButtonActionPerformed
                traceTreeRepresenter.expandCollapseButton(evt);
	}// GEN-LAST:event_expandCollapseButtonActionPerformed

	private void filterButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_filterButtonActionPerformed

		
		boolean result = false;		
		long startTime = System.currentTimeMillis();

		try {
			
			String selectedValue = filterValueComboBox.getSelectedItem()
					.toString();
			
			String selectedIndex = filterFieldComboBox.getSelectedItem()
					.toString();
			
			TraceLinkElementEnum selectedElement =  TraceLinkElementEnum.valueOfElement(selectedIndex);

			this.traceTreeRepresenter.filterButtonActionPerformed(evt, selectedElement, selectedValue);

			result = true;

		} catch (Exception ex) {
			result = false;
		}
		long endTime = System.currentTimeMillis();
		
                

		long duration = endTime - startTime;

		if (result) {
			messageLabel.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/success.png")));
			StringBuilder message = new StringBuilder();
			message.append("Trace links filtered successfully. ");			
			message.append(duration);
			message.append(" ms");

			messageLabel.setText(message.toString());
		} else {
			messageLabel.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/alert.png")));
			messageLabel
					.setText("Error while trying to filter trace links. See log for details");
		}

		

	}// GEN-LAST:event_filterButtonActionPerformed

	private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_closeButtonActionPerformed
		this.dispose();
	}// GEN-LAST:event_closeButtonActionPerformed

	private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_runButtonActionPerformed

            
		boolean result = false;
		int size = 0;
		long startTime = System.currentTimeMillis();

		try {

			String query = queryParameterTextArea.getText();
			String[] split = query.split(":", 2);

			// TODO:  Refatorar
//			QueryParameter param = new QueryParameter();
//			param.setField(split[0]);
//			param.setValue(split[1]);

			// TODO: refatorar
			TraceLinkList traceLinks = this.facade.queryTraceLinks(null);
			size = traceLinks.getTraceLinks().size();

                        

			result = traceTreeRepresenter.runButtonActionPerformed(evt, traceLinks);
			this.updateFilterButtons(traceLinks);
			this.traceTreeRepresenter.setLastQueriedResult(traceLinks);
		} catch (Exception ex) {
			result = false;
		}
                
		long endTime = System.currentTimeMillis();

		expand = false;

		
		long duration = endTime - startTime;

		if (result) {
			messageLabel.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/success.png")));
			StringBuilder message = new StringBuilder();
			message.append("Trace links queried successfully. ");
			message.append(size);
			message.append(" trace links found. ");
			message.append(duration);
			message.append(" ms");

			messageLabel.setText(message.toString());
		} else {
			messageLabel.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/alert.png")));
			messageLabel
					.setText("Error while trying to query trace links. See log for details");
		}

	}// GEN-LAST:event_runButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    
    // End of variables declaration//GEN-END:variables

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void updateFilterButtons(TraceLinkList traceLinks) {

		filterFieldComboBox.setModel(new javax.swing.DefaultComboBoxModel(
				new String[] {  "Select", 
								TraceLinkElementEnum.REQUIREMENT.toString(),
								TraceLinkElementEnum.SEMANTIC.toString(),
								TraceLinkElementEnum.ARTIFACT_TYPE.toString(),
								TraceLinkElementEnum.ARTIFACT.toString()
				}));

		filterValueComboBox.setModel(new javax.swing.DefaultComboBoxModel(
				new String[] { "Select" }));

	}

	class QuerySelectionListener implements ListSelectionListener {

		@SuppressWarnings("rawtypes")
		public void valueChanged(ListSelectionEvent e) {

			javax.swing.JList lsm = (javax.swing.JList) e.getSource();

			int curretIndex = lsm.getSelectedIndex();
			String key = queryList.getModel().getElementAt(curretIndex)
					.toString();
			TraceQuery query = mapQueries.get(key);

			queryParameterTextArea.setText("");

			// TODO: Refatorar
//			int i = 0;
//			for (QueryParameter param : query.getParameters()) {
//
//				if (i > 0) {
//					queryParameterTextArea.append(System.lineSeparator());
//				}
//				queryParameterTextArea.append(param.getField());
//				queryParameterTextArea.append(":");
//				queryParameterTextArea.append("<value>");
//				i++;
//			}

			messageLabel.setIcon(new javax.swing.ImageIcon(getClass()
					.getResource("/icons/warning.png")));
			messageLabel.setText("Change <value> tag(s) to desired value(s)");

		}

	}

}
